/**
  * @addtogroup gb_msg_32960
  * gb_msg_32960_session_comp
  * @{
 */
 /**
 * @file         gb_msg_32960_session_comp.h
 * @brief        gb32960会话组件
 * @note
 * @author       YinYan
 * @date         2023-01-04
 * @version      1.0
 *
 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2023-01-04  <td>1.0                   <td>YinYan          <td>创建初始版本
 * @copyright    杭州鸿泉物联网技术股份有限公司
 */
#ifndef _GB_MSG_32960_SESSION_COMP_H_
#define _GB_MSG_32960_SESSION_COMP_H_

#include "mfc/mfc_serial_vir_bus.h"
#include "mfc/mfc_string.h"
#include "gb_msg_32960_mgr.h"
#include "gb_msg_32960_session_interface.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * gb32960会话结果
 */
typedef enum TGbMsg32960SessionCompResultEnumTag TGbMsg32960SessionCompResultEnum;
enum TGbMsg32960SessionCompResultEnumTag
{
    kGbMsg32960SessionCompResultSuccess  =  0,   ///< 成功
    kGbMsg32960SessionCompResultFail     = -1,   ///< 失败
    kGbMsg32960SessionCompResultIllegal  = -2,   ///< 不合法(如: 参数不合法)
    kGbMsg32960SessionCompResultInvalid  = -3,   ///< 无效
    kGbMsg32960SessionCompResultNotExist = -4,   ///< 不存在
};


/**
 * gb32960会话属性枚举
 */
typedef enum TGbMsg32960SessionCompAttrEnumTag TGbMsg32960SessionCompAttrEnum;
enum TGbMsg32960SessionCompAttrEnumTag
{
    /// sim卡的iccid号
    /// param1: char *iccid，若传NULL,则忽略param2，返回长度
    /// param2: int *iccid长度
    /// 返回值: 实际获取的iccid长度
    kGbMsg32960SessionCompAttrICCID = 0,

    /// 可充电储能子系统个数
    /// 返回值: 可充电储能子系统个数
    kGbMsg32960SessionCompAttrEytSubCount = 1,

    /// 可充电储能系统编码长度
    /// 返回值: 可充电储能系统编码长度
    kGbMsg32960SessionCompAttrEytSubCodeLen = 2,

    /// 可充电储能系统编码
    /// param1: char *EytSubCode，若传NULL,则忽略param2，返回长度
    /// param2: int EytSubCode长度
    /// 返回值: 实际获取的EytSubCode长度
    kGbMsg32960SessionCompAttrEytSubCode = 3,

    /// 车辆VIN码
    /// param1: char *终端Id，若传NULL,则忽略param2，返回长度
    /// param2: int *终端Id长度
    /// 返回值: 实际获取的终端Id长度
    kGbMsg32960SessionCompAttrVehicleVin = 4,

    /// 服务器个数
    /// 返回值: 终端主备服务器个数
    kGbMsg32960SessionCompAttrServerHostCount = 5,

    /// 服务器参数，以冒号分割主机和端口
    /// param1: char *主备服务器，以冒号分割主机和端口,例如www.direct.com:10500
    /// param2: 高2字节: 主备服务器索引号，从0开始; 低2字节: buf长度
    kGbMsg32960SessionCompAttrServerHostParam = 6,

    /// 休眠关机时间
    /// 返回值: 时间戳
    kGbMsg32960SessionCompAttrLastSaveTime = 7,

    // 流水号
    kGbMsg32960SessionCompAttrLoginSeq = 8,

    // 会话状态
    kGbMsg32960SessionStatus = 9,
};

/**
 * gb32960会话获取属性事件
 * @param sender: 发起者
 * @param attr_type: 属性类型,参考TGbMsg32960SessionCompAttrEnum
 * @param param1: 参数1
 * @param param2: 参数2
 * @return 参考TGbMsg32960SessionCompResultEnum; >0: 全部是成功，表示长度; 0表示返回值也是成功，参见具体描述
 */
typedef int(*TGbMsg32960SessionCompDoAttrEvent)(void *sender, int attr_type, void *param1, long param2);

/**
 * gb32960会话获取属性事件
 * @param sender: 发起者
 * @param attr_type: 属性类型,参考TGbMsg32960SessionCompAttrEnum
 * @param param1: 参数1
 * @param param2: 参数2
 * @return 参考TGbMsg32960SessionCompResultEnum; >0: 全部是成功，表示长度; 0表示返回值也是成功，参见具体描述
 */
typedef int(*TGbMsg32960SessionCompDoSetAttrEvent)(void *sender, int attr_type, Int32 param);

/**
 * gb32960会话属性事件
 * @note 外部提供的此方法需与TGbMsg32960SessionCompRunOnce同一个线程
 */
typedef struct TGbMsg32960SessionCompOnAttrEventTag TGbMsg32960SessionCompOnAttrEvent;
struct TGbMsg32960SessionCompOnAttrEventTag
{
    void *object;  ///< 对象指针
    TGbMsg32960SessionCompDoAttrEvent Method;  ///< 读取方法
    TGbMsg32960SessionCompDoSetAttrEvent SetMethod; ///< 设置方法
};

/**
 * gb32960会话接收数据事件
 * @param sender: 发起者
 * @param buf: 数据缓存
 * @param size: 数据长度
 * @return
 */
typedef void(*TGbMsg32960SessionCompDoReceiveEvent)(void *sender, const Byte *buf, Int32 size);

typedef struct TGbMsg32960SessionCompOnRecvEventTag TGbMsg32960SessionCompOnRecvEvent;
struct TGbMsg32960SessionCompOnRecvEventTag
{
    void *object; ///< 对象指针
    TGbMsg32960SessionCompDoReceiveEvent  Method;   ///< 方法
};

/**
 * gb32960会话发送数据事件
 * @param sender: 发起者
 * @param buf: 数据缓存
 * @param size: 数据长度
 * @return
 */
typedef void(*TGbMsg32960SessionCompDoSendEvent)(void *sender, const Byte *buf, int size);

typedef struct TGbMsg32960SessionCompOnSendEventTag TGbMsg32960SessionCompOnSendEvent;
struct TGbMsg32960SessionCompOnSendEventTag
{
    void *object; ///< 对象指针
    TGbMsg32960SessionCompDoSendEvent  Method;  ///< 方法
};

/**
 * 会话状态
 */
typedef enum TGbMsg32960SessionCompStateEnumTag TGbMsg32960SessionCompStateEnum;
enum TGbMsg32960SessionCompStateEnumTag
{
    kGbMsg32960SessionCompStateDisconnect  = 0,    ///< 断开连接
    kGbMsg32960SessionCompStateConnectOk   = 1,    ///< 连接成功, 带参数host和port
    kGbMsg32960SessionCompStateConnectFail = 2,    ///< 连接失败，带参数host和port
    kGbMsg32960SessionCompStateLogining    = 3,    ///< 登录中
    kGbMsg32960SessionCompStateLoginOk     = 4,    ///< 登录成功
    kGbMsg32960SessionCompStateLoginFail   = 5,    ///< 登录失败
    kGbMsg32960SessionCompStateLogout      = 6,    ///< 登出
};


typedef void(*TGbMsg32960SessionCompDoStateNotify)(void *sender, TGbMsg32960SessionCompStateEnum state, const void *param, Int32 param_len);

/**
 * 状态通知
 */
typedef struct TGbMsg32960SessionCompOnStateNotifyTag TGbMsg32960SessionCompOnStateNotify;
struct TGbMsg32960SessionCompOnStateNotifyTag
{
    void *object;
    TGbMsg32960SessionCompDoStateNotify Method;
};

/**
 * gb32960引擎
 */
typedef struct TGbMsg32960SessionCompTag TGbMsg32960SessionComp;
struct TGbMsg32960SessionCompTag
{
    TOfObject parent_;                      ///< 基类

PROTECTED
    TOfVirtualMethod Destroy_;              ///< 析构事件
    IGbMsg32960Session session_;
PUBLIC
    TGbMsg32960SessionCompOnAttrEvent OnAttrEvent;        ///< 属性获取事件,Init之前设置好
    TGbMsg32960SessionCompOnRecvEvent OnRecvEvent;        ///< 接收消息事件
    TGbMsg32960SessionCompOnSendEvent OnSendEvent;        ///< 发送消息事件
    TGbMsg32960SessionCompOnStateNotify OnStateNotify;    ///< 状态通知事件
    TGbMsg32960Mgr *msg_mgr_;                 ///< 消息管理器

PRIVATE
    TMfSerialVirBus *serial_vir_bus;        ///< 虚拟串行总线对象
    TGbMsg32960 *msg_vehicle_logon_;        ///< 车辆登录消息
    TGbMsg32960 *msg_vehicle_logout_;       ///< 车辆登出消息

    DWord last_login_sec_;                  ///< 最后一次登入时间,单位: s
    DWord last_logout_sec_;                 ///< 最后一次登出时间,单位: s
    DWord last_connect_tick_;               ///< 最后一次连接时间,单位: ms
    Int32 connect_intv_;                    ///< 连接间隔,单位:ms
    Int32 login_sec_;                       ///< 3次内登入间隔,单位:s
    Int32 login_min_;                       ///< 3次登入失败后再次登入间隔，单位：min
    Int32 recv_size_;                       ///< 接收大小
    Byte *recv_buf_;                        ///< 接收缓冲
    Int32 recv_buf_size_;
    Byte *decode_buf_;                      ///< 解码缓冲
    Int32 decode_buf_size_;                 ///< 解码缓冲
    Byte *encode_buf_;
    Int32 encode_buf_size;
    TMfString connect_ip_;
    UInt16 port_;
    Byte net_state_;                        ///< 网络状态
    Byte session_state_;                    ///< 会话状态
    Bool timing_send_heartbeat_;            ///< 是否定时发送心跳,默认：True
    Bool param_motify_enable_;              ///< 参数设置使能,默认:True
    Int32 host_index_;
    Int32 heartbeat_time_intv_;             ///< 心跳的时间间隔,单位: 毫秒
    DWord last_heartbeat_time_;             ///< 最后心跳时间,单位: 毫秒
    DWord last_recv_server_heartbeat_time_; ///< 最后服务器的心跳时间,单位: 毫秒

    Int32 recv_timeout_disconn_intv_;       ///< 正常工作(车辆登录除外)时多久没有收到服务器的数据,则断开,单位: 秒
    Bool  comm_mode_;                       ///< 串口模式
    Byte zone_;                             ///< zone范围0-240,偏移量120，表示-12-+12，最小单位0.1
};

/**
 * 构造函数
 * @param self: 对象指针
 * @param msg_mgr: 消息管理器
 * @param serial_vir_bus: 虚拟总线对象
 * @param recv_buf: 接收缓存
 * @param recv_buf_size: 接收缓存大小
 * @param temp_buf: 临时缓存
 * @param temp_buf_size: 临时缓存大小
 * @return
*/
void TGbMsg32960SessionCompCreate(TGbMsg32960SessionComp *self, TGbMsg32960Mgr *msg_mgr, TMfSerialVirBus *serial_vir_bus,
    Byte *recv_buf, Int32 recv_buf_size, Byte *encode_buf, Int32 encode_buf_size, Byte *decode_buf, Int32 decode_buf_size);

/**
 * 获取消息管理器指针
 * @param self: 对象指针
 * @return 消息管理器指针
 */
TGbMsg32960Mgr *TGbMsg32960SessionCompMsgMgr(TGbMsg32960SessionComp *self);

/**
 * 初始化
 * @param self: 对象指针
 * @return True: 成功; False: 失败
 */
Bool TGbMsg32960SessionCompInit(TGbMsg32960SessionComp *self);

/**
 * 执行一次函数，需要cpu调度
 * @param self: 对象指针
 * @return
 */
void TGbMsg32960SessionCompRunOnce(TGbMsg32960SessionComp *self);

/**
 * 去初始化
 * @param self: 对象指针
 * @return
 */
void TGbMsg32960SessionCompDone(TGbMsg32960SessionComp *self);

/**
 * 发送消息
 * @param self: 对象指针
 * @param msg: 需要发送的消息,内部不会释放消息
 * @param encode_success: 编码是否成功,若为NULL，则忽略参数,编码失败一般指长度超过1024
 * @return True: 成功; False: 失败
 * @note 发送成功肯定是编码成功，发送失败可能是编码失败或者参数为空
 */
Bool TGbMsg32960SessionCompSendMsg(TGbMsg32960SessionComp *self, TGbMsg32960 *msg, Bool *encode_success);

/**
 * 发送数据
 * @param self: 对象指针
 * @param data: 需要发送的数据
 * @param data_size: 数据大小
 * @return > 0: 实际发送的数据大小; <0: 参数错误; 0: 网络未鉴权成功，也有可能总线底层无缓冲
 * @note 不能保证data_size一次性能全部发出去,内部会判断已经处于鉴权成功状态下才允许发送数据
 */
Int32 TGbMsg32960SessionCompSendData(TGbMsg32960SessionComp *self, const void *data, Int32 data_size);

/**
* 目前是否已经登录成功，处于在线状态
* @param self: 对象指针
* @return True: 在线状态; False: 不在线状态
* @note : 需要扩展，解决注册过程中的状态开发
*/
Bool TGbMsg32960SessionCompIsOnLine(TGbMsg32960SessionComp *self);

/**
* 设置心跳时间间隔
* @param self: 对象指针
* @param value: 心跳间隔,单位: 秒
* @note 有效范围1s-240s
* @return
*/
void TGbMsg32960SessonSetHeartbeatTimeIntv(TGbMsg32960SessionComp *self, Int32 value);

/**
* 获取心跳时间间隔，默认30秒
* @param self: 对象指针
* @return 心跳间隔: 单位: 秒
*/
Int32 TGbMsg32960SessionCompHeartbeatTimeIntv(TGbMsg32960SessionComp *self);

/**
* 设置多久没有收到数据，断开连接
* @param self: 对象指针
* @param value: 断开间隔,单位: 秒
* @note 内部限制最短时间30秒
* @return
*/
void TGbMsg32960SessonSetRecvTimeoutDisconnIntv(TGbMsg32960SessionComp *self, Int32 value);

/**
* 获取断开连接时间间隔，默认120秒
* @param self: 对象指针
* @return 断开连接时间间隔, 单位: 秒
*/
Int32 TGbMsg32960SessionCompRecvTimeoutDisconnIntv(TGbMsg32960SessionComp *self);

/**
* 获取会话状态
* @param self: 对象指针
* @return 会话状态
*/
TGbMsg32960SessionCompStateEnum TGbMsg32960SessionCompState(TGbMsg32960SessionComp *self);

/**
* 获取当前通道的会话参数修改使能,主要针对0x8103参数设置
* @param self: 对象指针
* @return True: 可设置; False: 不可设置
*/
Bool TGbMsg32960SessionCompParamMotifyEnable(TGbMsg32960SessionComp *self);

/**
* 设置当前通道的会话参数修改使能,主要针对0x81参数设置
* @param self: 对象指针
* @param enable: True: 可设置0x81; False: 不可设置0x81
* @return
*/
void TGbMsg32960SessionCompSetParamMotifyEnable(TGbMsg32960SessionComp *self, Bool enable);

/**
* 获取会话接口
* @param self: 对象指针
* @return 会话接口
*/
IGbMsg32960Session *TGbMsg32960SessionCompSession(TGbMsg32960SessionComp *self);

/**
* 设置到串口模式
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompSetCommMode(TGbMsg32960SessionComp *self);

/**
* 设置时区，不设置默认为东八区
* @param self: 对象指针
* @param zone: 时区，0-240.偏移量120，表示-12.0~+12.0，最小单位0.1，与0时区相差(0.1*zone-12)*3600s
* @return
*/
void TGbMsg32960SessionCompSetZone(TGbMsg32960SessionComp *self,const Byte zone);

/**
* 设置登入间隔
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompSetLoginSec(TGbMsg32960SessionComp *self, Int32 sec);

/**
* 3次登录失败后再次登录间隔,1-240min
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompSetLoginMin(TGbMsg32960SessionComp *self, Int32 min);


/**
* 模拟车辆登出接口
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompVechleLogout(TGbMsg32960SessionComp *self);

/**
* 模拟车辆登入接口
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompVechleLogin(TGbMsg32960SessionComp *self);

/**
* 断网模拟
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompVechleDisConnect(TGbMsg32960SessionComp *self);


/**
* 模拟登入，设置快速连接，无效等待30s
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompVechleSetQuikConnect(TGbMsg32960SessionComp *self);

/**
* 网络状态设置为登出状态
* @param self: 对象指针
* @return
*/
void TGbMsg32960SessionCompNetStateSetLogouting(TGbMsg32960SessionComp *self);

#ifdef __cplusplus
} // extern "C" {
#endif
#endif

